/***************************************************************************
 *   Copyright (C) 2009 by umbacos@gmail.com                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "udm-common.h"

char* dcgi;
char* droo;
char* dbin;
char* wget;
char* ctor;
char* dwww;
char* dufb;
char* ddnl;
char* dtrk;
char* fcnf;
char* argv0;
char* filter;
char* pidfile;

void get_post_cookie();
void get_directories ( char * file );
void * xmalloc ( size_t size );
char * getPID ( char* file );
char * pipe_cmd ( const char * cmd );
int filter_select ( struct dirent *entry );
void print_headers ( int final );
void send_message ( char * msg, char * inf );
char * escape_hyphens ( char * str, char * ch );
void strip_last ( char * str, char ch );

void log_error(char * path){
	char * m_err;

	switch ( errno ) {
		case EACCES	:m_err = "EACCESS";	break;
		case EBUSY	:m_err = "EBUSY";	break;
		case EFAULT	:m_err = "EFAULT";	break;
		case EINVAL	:m_err = "EINVAL";	break;
		case EISDIR	:m_err = "EISDIR";	break;
		case ELOOP	:m_err = "ELOOP";	break;
		case EMLINK	:m_err = "EMLINK";	break;
		case ENAMETOOLONG:m_err = "ENAMETOOLONG";	break;
		case ENOENT	:m_err = "ENOENT";	break;
		case ENOMEM	:m_err = "ENOMEM";	break;
		case ENOSPC	:m_err = "ENOSPC";	break;
		case ENOTDIR	:m_err = "ENOTDIR";	break;
		case ENOTEMPTY	:m_err = "ENOTEMPTY OR EEXIST";	break;
		case EEXIST	:m_err = "ENOTEMPTY OR EEXIST";	break;
		case EPERM	:m_err = "EPERM";	break;
		case EROFS	:m_err = "EROFS";	break;
		case EXDEV	:m_err = "EXDEV";	break;
	}

#ifdef DEBUG
	mylog ( "error: ", path );
	mylog ( "error: ", m_err );
#endif
	send_message ( m_err, path );
}

static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char * decode64(char * input) {
  unsigned char chr1, chr2, chr3;
  unsigned char enc1, enc2, enc3, enc4;

  char * output = xmalloc (strlen(input));
  int i = 0;

  do {
	 enc1 = strchr(cb64,input[i++]) - cb64;
	 enc2 = strchr(cb64,input[i++]) - cb64;
	 enc3 = strchr(cb64,input[i++]) - cb64;
	 enc4 = strchr(cb64,input[i++]) - cb64;

	 chr1 = (enc1 << 2) | (enc2 >> 4);
	 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
	 chr3 = ((enc3 & 3) << 6) | enc4;

	 output[i/4*3-3] = (char) chr1;

	 if (enc3 != 64) {
		 output[i/4*3-2] = (char) chr2;
	 }
	 if (enc4 != 64) {
		 output[i/4*3-1] = (char) chr3;
	 }

	 chr1 = chr2 = chr3 = '\0';
	 enc1 = enc2 = enc3 = enc4 = '\0';

  } while (i < strlen(input));

  return output;
}

/* recursive directory remove */
void my_remove ( char* path ) {
	int n;
	int r;

#ifdef DEBUG
	mylog ( "enter my_remove:", path );
#endif
	struct dirent **namelist;
	struct stat buf;

	if (stat ( path, &buf ) < 0) log_error ( path );

	if ( ! S_ISDIR ( buf.st_mode ) ) {
#ifdef DEBUG
	mylog ( "unlink:", path );
#endif
		if ( unlink ( path ) < 0 )
			log_error(path);
		return;
	}

	filter = "";

	if ( ( n = scandir ( path, &namelist, ( void * ) filter_select, NULL ) ) < 0 )
		send_message ( "my_remove error: ", path );

	while ( n-- ) {
		r = chdir ( path );
		my_remove ( namelist[n]->d_name );
		free ( namelist[n] );
	}

	free ( namelist );
#ifdef DEBUG
	mylog ( "rmdir:", path );
#endif
	r = chdir ( ".." );
	if ( rmdir ( path ) < 0 )
		log_error(path);
	return;

}

/* Start wget */
void start_wget ( char * url, char * para, char * trk ) {
	char flog[500];
	char cmdp[1000];
	char * pipd;
	FILE * df;
	int r;

	memset ( &flog, 0, 500 );
	memset ( &cmdp, 0, 1000 );

	if ( trk == NULL ) {
		strcat ( strcpy ( flog, dtrk ), "XXXXXX" );
		mkstemp ( flog );
		strcat ( flog, FILTER_WGT );
	} else {
		strcpy ( flog, trk );
	}

	strcpy ( cmdp, ddnl );
	if ( getenv ( "FORM_curdir" ) )
		strncat ( cmdp, getenv ( "FORM_curdir" ), 1000 - strlen ( ddnl ) );
	r = chdir ( cmdp );

	sprintf ( cmdp, "%s -b --progress=bar:force %s -a \"%s\" \"%s\"" ,
	                wget,                    para,   escape_hyphens(flog,"\""),  url );
	pipd = pipe_cmd ( cmdp );
	pipd = rindex ( pipd, ' ' ) + 1;
	strip_last ( pipd, '.' );

#ifdef DEBUG
	mylog ( "popen:", cmdp );
	mylog ( flog, ":tracker" );
#endif

	strip_last ( flog, '.' );
	if ( ( df = fopen ( flog, "w" ) ) == NULL )
		send_message ( "Unable to write trk file:", flog );
	fprintf ( df, "%s\n", pipd );
	fprintf ( df, "%s\n", url );
	fprintf ( df, "%s\n", para );
	fclose ( df );
}

/* Start Megaupload */
void do_megaupload ( char * url, char * para ) {

	char flog[500];
	char flig[500];
	char cmdp[1000];
	char * pipd;
	FILE * df;
	int r;

	memset ( &flog, 0, 500 );
	memset ( &flig, 0, 500 );
	memset ( &cmdp, 0, 1000 );

	strcat ( strcpy ( flog, dtrk ), "XXXXXX" );
	mkstemp ( flog );
	strcpy ( flig, FILTER_WGT );

	strcpy ( cmdp, ddnl );
	if ( getenv ( "FORM_curdir" ) )
		strncat ( cmdp, getenv ( "FORM_curdir" ), 1000 - strlen ( ddnl ) );
	r = chdir ( cmdp );

	sprintf ( cmdp, "%s --save-cookies \"%s.ck\" --post-data \"%s\" -O - http://www.megaupload.com/?c=account > /dev/null" ,
	                wget,              escape_hyphens(flog,"\""),            para);
#ifdef DEBUG
	mylog ( "popen:", cmdp );
#endif
	pipd = pipe_cmd ( cmdp );
#ifdef DEBUG
	mylog ( "result:", pipd );
#endif

	sprintf ( cmdp, "%s -b -c --load-cookies \"%s.ck\" --progress=bar:force -a \"%s%s\" %s" ,
	                wget,                    escape_hyphens(flog,"\""),   escape_hyphens(flog,"\""), flig, url );
	pipd = pipe_cmd ( cmdp );
	pipd = rindex ( pipd, ' ' ) + 1;
	strip_last ( pipd, '.' );

#ifdef DEBUG
	mylog ( "popen:", cmdp );
	mylog ( flog, ":tracker" );
#endif

	if ( ( df = fopen ( flog, "w" ) ) == NULL )
		send_message ( "Unable to write trk file:", flog );
	fprintf ( df, "%s\n", pipd );
	fprintf ( df, "%s\n", url );
	fprintf ( df, "%s\n", para );
	fclose ( df );
}

void start_ctor ( char * url, char * para, char * trk ) {
	char cmdp[1000];
	char murl[1000];
	char ftrk[ 500];
	char flog[ 500];
	char * fdat;
	char * pipd;
	char * entry;
	char * fnam;
	int r;

	struct tm * mtime;
	time_t * tt;
	FILE * df;

	memset ( &cmdp, 0, 1000 );
	memset ( &murl, 0, 1000 );
	memset ( &ftrk, 0,  500 );
	memset ( &flog, 0,  500 );

	r = chdir (dtrk);

	if ( trk == NULL ) {
		mkstemp ( strcpy ( ftrk, "XXXXXX" ) );
		strcat ( ftrk, FILTER_TOR );
		sprintf ( murl, "%s%s", ddnl, url );
		strcpy ( flog, dtrk );

	} else {
		strcpy ( ftrk, trk );
		strcpy ( murl, url );
	}

	strcat ( flog, ftrk );

	time ( ( time_t * ) &tt );
	mtime = gmtime ( ( time_t * ) & tt );

	fnam = rindex ( murl, '/' ) + 1;

#ifdef DEBUG
	mylog ( "tracker:", flog );
#endif

	if ( ( df = fopen ( flog, "w" ) ) == NULL )
		send_message ( "Unable to write trk file:", flog );

	fprintf ( df, "-- %0d/%0d/%d %0d:%0d:%0d --%s\n", mtime->tm_mday, mtime->tm_mon, 1900 + mtime->tm_year,
	          mtime->tm_hour, mtime->tm_min, mtime->tm_sec, fnam );

	fclose ( df );

	fdat = strdup ( flog );
	strip_last ( fdat, '.' );
	entry = basename ( fdat );

	strcpy ( cmdp, ddnl );
	if ( getenv ( "FORM_curdir" ) )
		strncat ( cmdp, getenv ( "FORM_curdir" ), 1000 - strlen ( ddnl ) );
	r = chdir ( cmdp );

	if ( ( df = fopen ( "/tmp/udm-sl", "w" ) ) == NULL )
		send_message ( "Unable to write file /tmp/udm-sl", "" );
	if (getenv ( "FORM_ctorAlternateStatusLine" )[0] == '1')	// Alternate Status Line
		fprintf ( df, "07" );
	else					// Standard Status Line
		fprintf ( df, "06" );
	fclose ( df );

	sprintf ( cmdp, "%s -P %s %s -b %s%s.bf \"%s\" < /tmp/udm-sl >> %s 2>> %s & echo -n $!",
		         ctor, entry,  para, dtrk,  entry,      escape_hyphens(murl,"\""), flog,  flog );
#ifdef DEBUG
	mylog ( "popen:", cmdp );
#endif
	pipd = pipe_cmd ( cmdp );

#ifdef DEBUG
	mylog ( "tracker:", fdat );
#endif
	if ( ( df = fopen ( fdat, "w" ) ) == NULL )
		send_message ( "Unable to write trk file:", fdat );
	fprintf ( df, "%s\n", pipd );
	fprintf ( df, "%s\n", murl );
	fprintf ( df, "%s\n", para );
	fclose ( df );
}

void do_meta ( char * url ) {
	char cmdp[1000];
	char * pipd;

	memset ( &cmdp, 0, 1000 );

	strcpy ( cmdp, ddnl );
	if ( getenv ( "FORM_curdir" ) )
		strncat ( cmdp, getenv ( "FORM_curdir" ), 1000 - strlen ( ddnl ) );
	chdir ( cmdp );

	sprintf ( cmdp, "%s -x %s", ctor, escape_hyphens(url,"\""));
#ifdef DEBUG
	mylog ( "popen:", cmdp );
#endif
	pipd = pipe_cmd ( cmdp );
#ifdef DEBUG
	mylog ( "meta:", pipd );
#endif
	send_message ( pipd, "" );
}

/* Start wget or ctorrent, depending on func parameter, given a tracker */
void do_start_action ( char * trk, void ( *func ) ( void *, void *, void * ) ) {
	char pid[10];
	char url[1000];
	char para[1000];
	char flog[500];
	char fdat[500];
	char * ftrk;
	FILE * df;
	char * q;

	memset ( &pid, 0, 10 );
	memset ( &url, 0, 1000 );
	memset ( &para, 0, 1000 );
	memset ( &flog, 0, 500 );
	memset ( &fdat, 0, 500 );

	ftrk = strdup ( trk );
	strip_last ( ftrk, '.' );

	sprintf ( flog, "%s%s", dtrk, trk );
	sprintf ( fdat, "%s%s", dtrk, ftrk );

	if ( ( df = fopen ( fdat, "r" ) ) == NULL )
		send_message ( "Unable to read trk file:", fdat );
	q = fgets ( pid, 10, df );
	q = fgets ( url, 1000, df );
	q = fgets ( para, 1000, df );
	fclose ( df );

	strip_last ( url, '\n' );
	strip_last ( para, '\n' );

	func ( url, para, flog );
}

/* Stop a process */
void do_stop ( char * fil ) {
	char * entry;
	if ( strlen ( entry = getPID ( fil ) ) != 0 ) {
#ifdef DEBUG
	mylog ( "stopping process: ", entry );
#endif
		kill ( ( pid_t ) atoi ( entry ), SIGTERM );
		sleep ( 1 );
		kill ( ( pid_t ) atoi ( entry ), SIGTERM );
	} else {
#ifdef DEBUG
	mylog ( "no process for: ", fil );
#endif
	}
}

/* Delete a tracker */
void do_delete ( char * fil ) {
	char ntrk[1000];

	memset ( &ntrk, 0, 1000 );
	do_stop ( fil );
	strcat ( strcpy ( ntrk, dtrk ), fil );

	if ( strstr ( ntrk, "/.." ) != NULL )
		send_message ( "filename error (contains /..)", ntrk );

	unlink ( ntrk );
	strip_last ( ntrk, '.' );
	unlink ( ntrk );
	strcat ( ntrk, ".bf" );
	unlink ( ntrk );
	strip_last ( ntrk, '.' );
	strcat ( ntrk, ".ck" );
	unlink ( ntrk );
}

/* Remove a downloaded file */
void do_remove ( char * fil ) {
	char ndnl[1000];

	memset ( &ndnl, 0, 1000 );

	sprintf ( ndnl, "%s%s", ddnl , fil );
	if ( strstr ( ndnl, "/.." ) != NULL )
		send_message ( "filename error (contains /..)", ndnl );
	my_remove ( ndnl );
}

/* Kill all downloads and delete all trackers */
void do_killall() {

	int n;
	struct dirent **namelist;

	pipe_cmd ( "killall ctorrent" );
	pipe_cmd ( "killall wget" );
	/* ctorrent on the second SIGTERM should actually quit */
	pipe_cmd ( "killall ctorrent" );
	sleep ( 2 );

	filter = "";

	n = chdir ( dtrk );
	if ( ( n = scandir ( dtrk, &namelist, ( void * ) filter_select, NULL ) ) < 0 )
		send_message ( "nukeall error: ", dtrk );

	while ( n-- ) {
		unlink ( namelist[n]->d_name );
		free ( namelist[n] );
	}

	free ( namelist );
}

/* Execute a command shell */
void do_cmd(char * cmd) {

	chdir ( ddnl );
	send_message ( pipe_cmd ( cmd ), "\n" );

}
void do_amule(char * cmd) {

	char pcmd[1000];
	chdir ( dtrk );
#ifdef DEBUG
	mylog ("executing: amulecmd -c ", cmd);
#endif
	sprintf ( pcmd, "amulecmd -c \"%s\"", escape_hyphens( cmd , "\"" ) );
	send_message ( pipe_cmd ( pcmd ), "\n" );

}
void do_amure() {

	chdir ( dtrk );
#ifdef DEBUG
	mylog ("executing: amulecmd -c \"show dl\" > amule.amu", "");
#endif
	pipe_cmd ( "amulecmd -c \"show dl\" > amule.amu" );

}

/* Read df info */
void do_disk () {

	char pip[1000];

	memset ( &pip, 0, 1000 );
	sprintf ( pip, "df -k \"%s\"", escape_hyphens( ddnl , "\"" ) );
	send_message ( pipe_cmd ( pip ) , "" );

}

void do_rename ( char * old, char * new ) {

	struct stat statbuf;
	char pold[1000];
	char pnew[1000];
	memset ( &pold, 0, 1000 );
	memset ( &pnew, 0, 1000 );

	if ( strstr ( new, "/.." ) != NULL )
		send_message ( "Filename error (contains /..)", new );

	sprintf ( pold, "%s%s", ddnl, old );
	sprintf ( pnew, "%s%s", ddnl, new );

#ifdef DEBUG
	mylog ("rename from:", pold);
	mylog ("rename to:  ", pnew);
#endif
	if ( stat ( pold, &statbuf ) < 0 )
		send_message ( "File not found:", pold );
	if ( rename ( pold, pnew ) < 0 )
		log_error(pold);
}

void do_copy ( char * src, char * dest ) {

	char cmdp[1000];
	char * pipd;
	struct stat buf;
	char * is_dir;

	sprintf ( cmdp, "%s%s" , ddnl, src );
	stat ( cmdp, &buf );
	if ( S_ISDIR ( buf.st_mode ) )
		is_dir = "-R";
	else
		is_dir = "";
	sprintf ( cmdp, "cp %s \"%s%s\" \"%s%s\"" , is_dir, ddnl, escape_hyphens(src,"\""), ddnl, escape_hyphens(dest,"\"") );

#ifdef DEBUG
	mylog ( "popen:", cmdp );
#endif

	pipd = pipe_cmd ( cmdp );

#ifdef DEBUG
	mylog ( "return:", pipd );
#endif
}

void do_tar ( char * src ) {

	char cmdp[1000];
	char * pipd;
	struct stat buf;
	char * bname;

	sprintf ( cmdp, "%s%s" , ddnl, dirname ( strdup ( src ) ) );
	chdir ( cmdp );
#ifdef DEBUG
	mylog ( "chdir:", cmdp );
	mylog ( "pwd:  ", pipe_cmd ( "pwd" ));
#endif

	bname = escape_hyphens ( basename ( strdup ( src ) ) ,"\"" );
	sprintf ( cmdp, "tar cvf \"%s.tar\" \"%s\"" , bname , bname );

#ifdef DEBUG
	mylog ( "popen:", cmdp );
#endif

	pipd = pipe_cmd ( cmdp );

#ifdef DEBUG
	mylog ( "return:", pipd );
#endif

	sprintf ( cmdp, "gzip \"%s.tar\"" , bname );

#ifdef DEBUG
	mylog ( "popen:", cmdp );
#endif

	pipd = pipe_cmd ( cmdp );

#ifdef DEBUG
	mylog ( "return:", pipd );
#endif
}

void do_mkdir ( char * path ) {

	char cmdp[1000];
	int r;

	sprintf ( cmdp, "%s%s" , ddnl, path );

	if (mkdir ( cmdp, DEFFILEMODE ))
		log_error ( cmdp );
}

void do_lock ( char * what ) {

	char cmdp[1000];
	char * user;
	char * pass;
	char * fibr;
	char * q;
	FILE * df;
	struct stat buf;

	if ( strcmp ( what, "read" ) == 0 ) {
		// Check if auth is enabled
		sprintf ( cmdp, "%s.htpasswd" , dwww );
		if ( stat ( cmdp, &buf ) ) 	send_message ( "KO", "" );
		else				send_message ( "OK", "" );
	} else if ( strcmp ( what, "unlock" ) == 0 ) {
		// Disable auth
		chdir ( dwww ); unlink ( ".htpasswd" ); unlink ( "trk/.htpasswd" ); unlink ( "cgi-bin/.htpasswd" );
		chdir ( dufb ); unlink ( ".htpasswd" ); unlink ( "cgi-bin/.htpasswd" );
		send_message ( "Close and restart the browser to complete the operation", "" );

	} else {
		// Validation
		sprintf ( cmdp, "" );
		if ( strlen(what) == 1 ) sprintf ( cmdp, "Insert username and password to enable Basic Authentication<br>", "<br>Basic Authentication was not enabled" );
		if ( what[0] == ':' ) sprintf ( cmdp, "%sUsername must be between 6 and 10 chars long<br>", cmdp );
		if ( what[strlen(what)-1] == ':' ) sprintf ( cmdp, "%sPassword must be between 6 and 10 chars long<br>", cmdp );
		if ( strlen ( cmdp ) > 0 ) send_message ( cmdp, "<br>Basic Authentication was not enabled" );

		user = strtok ( what, ":" );
#ifdef DEBUG
	mylog("user:",user);
#endif
		pass = decode64( strtok ( NULL, ":" ));
#ifdef DEBUG
	mylog("pass:",pass);
#endif
		fibr = strtok ( NULL, ":" );
#ifdef DEBUG
	mylog("fibr:",fibr);
#endif
		if ( ( strlen ( user ) < 6 ) || ( strlen ( user ) > 10) ) sprintf ( cmdp, "Username must be between 6 and 10 chars long<br>" );
		if ( ( strlen ( pass ) < 6 ) || ( strlen ( user ) > 10) ) sprintf ( cmdp, "%sPassword must be between 6 and 10 chars long<br>", cmdp );
		if ( strlen ( cmdp ) > 0 ) send_message ( cmdp, "<br>Basic Authentication was not enabled" );

		// Create htpasswd files
		chdir ( dwww );
		sprintf ( cmdp, "echo '%s' | %shtpasswd -c %s.htpasswd '%s' && cp .htpasswd trk && cp .htpasswd cgi-bin" , escape_hyphens ( pass, "'"), dbin, dwww, escape_hyphens ( user, "'") );
		user = pipe_cmd ( cmdp );

		if (fibr[0]=='1') {
			chdir ( dwww );
			sprintf ( cmdp, "cp .htpasswd %s && cp .htpasswd %s/cgi-bin", dufb, dufb );
			user = pipe_cmd ( cmdp );
		}
		send_message ( "Close and restart the browser to complete the operation", "" );
	}
	send_message ( "Error", "do_lock" );
}

void do_scripts(char * file){
	char entry[200];
	char olist[1000];
	struct dirent **namelist;
	int n;

	memset ( entry, 0, 200 );
	memset ( olist, 0, 1000 );

	strcat ( strcpy ( entry, droo ), "scripts/" );

	if (strlen(file)>0) {
		strcat ( entry , file );
		do_cmd ( entry );
	} else {
		filter = "";
		if ( ( n = scandir ( entry, &namelist, ( void * ) filter_select, NULL ) ) < 0 )
			send_message ( "Can't scan scripts directory:\n", entry );

		while ( n-- ) {
			strcat ( olist, "<option value=\"");
			strcat ( olist, namelist[n]->d_name);
			strcat ( olist, "\">" );
			strcat ( olist, namelist[n]->d_name);
			strcat ( olist, "</option>\n");
			free ( namelist[n] );
		}

		free ( namelist );
		send_message ( olist, "" );
	}
}

void do_fb(){
	if (dufb[strlen(dufb)-1]=='/') strip_last(dufb, '/');
	send_message ( "Location", rindex(dufb,'/') );
}

int main ( int argc, char** argv ) {

	char * qs;
	char * ntrk = xmalloc ( 1000 );
	char * entry;
	char cmd[11];
	char fil[501];
	char par[501];

	memset ( &cmd, 0, 10 );
	memset ( &fil, 0, 500 );
	memset ( &par, 0, 500 );

	get_directories ( strdup ( argv[0] ) );
	get_post_cookie ();

	if ( getenv ( "FORM_cmd" ) )
		strncpy ( cmd, getenv ( "FORM_cmd" ), 10 );
	else
		send_message ( "zcmd: no command provided", NULL );

	if ( getenv ( "FORM_file" ) )
		strncpy ( fil, getenv ( "FORM_file" ), 500 );

	if ( getenv ( "FORM_para" ) )
		strncpy ( par, getenv ( "FORM_para" ), 500 );
#ifdef DEBUG
	mylog ( "fil:", fil );
	mylog ( "cmd:", cmd );
	mylog ( "par:", par );
#endif

	/* Interpret */
	if ( strstr ( cmd, CMD_NUKEALL ) != 0 )	do_killall();
	else if ( strstr ( cmd, CMD_FB )    != 0 ) do_fb ();
	else if ( strstr ( cmd, CMD_DISK )    != 0 ) do_disk ();
	else if ( strstr ( cmd, CMD_AMURE )  != 0 ) do_amure ();
	else if ( strstr ( cmd, CMD_SCRIPTS )    != 0 ) do_scripts (fil);
	else if ( strstr ( cmd, CMD_TAR )  != 0 ) do_tar ( fil );
	else if ( strstr ( cmd, CMD_META )  != 0 ) do_meta ( fil );
	else if ( strstr ( cmd, CMD_RUN )  != 0 ) do_cmd ( fil );
	else if ( strstr ( cmd, CMD_AMULE )  != 0 ) do_amule ( fil );
	else if ( strstr ( cmd, CMD_LOCK )    != 0 ) do_lock ( fil );
	else if ( strstr ( cmd, CMD_DELETE )  != 0 ) do_delete ( fil );
	else if ( strstr ( cmd, CMD_REMOVE )  != 0 ) do_remove ( fil );
	else if ( strstr ( cmd, CMD_STOP )    != 0 ) do_stop ( fil );
	else if ( strstr ( cmd, CMD_MKDIR )    != 0 ) do_mkdir ( fil );
	else if ( strstr ( cmd, CMD_MEGAUPLOAD )    != 0 ) do_megaupload ( fil, par );
	else if ( strstr ( cmd, CMD_STARTDNL ) != 0 ) do_start_action ( fil, ( void * ) start_wget );
	else if ( strstr ( cmd, CMD_STARTTOR ) != 0 ) do_start_action ( fil, ( void * ) start_ctor );
	else if ( strstr ( cmd, CMD_CTOR )    != 0 ) start_ctor ( fil, par, NULL );
	else if ( strstr ( cmd, CMD_WGET )    != 0 ) start_wget ( fil, par, NULL );
	else if ( strstr ( cmd, CMD_RENAME )  != 0 )	do_rename ( fil, par );
	else if ( strstr ( cmd, CMD_COPY )  != 0 )	do_copy ( fil, par );
	else send_message ( "Unknown command:", cmd );

	send_message ( "OK", "" );

	return 0;
}
